/**
 * WTF Engine
 *
 * License... etc.
 **
 * XML Wrapper Classes
 **
 * Author: Sean Micklethwaite
 **/

#ifndef __xmlH__
#define __xmlH__

#include "config.h"

#ifdef __XML_XERCES__
#	include <xercesc/parsers/XercesDOMParser.hpp>
#	include <xercesc/dom/DOM.hpp>
	XERCES_CPP_NAMESPACE_USE
#elif defined(__XML_LIBXMLPP__)
#	include <libxml++/libxml++.h>
#endif

#include <sstream>
#include "string.h"

namespace WtfEngine
{
#ifdef __XML_XERCES__

	class XmlIterator {
	protected:
		DOMNode *			mpRoot;
		DOMNode *			mpNode;
	
		inline XmlIterator(DOMNode * pNode): mpRoot(pNode), mpNode(pNode) {
		};

	public:
		String GetXml();
		// Returns the inner text of the node
		String GetText();

		/**** Delegates ****/ 

		// Returns the value of the specified attribute of the current node
		String GetAttribute(const String& sName);

		template <typename T>
		inline T GetAttribute(const String& sName){
			T v;
			String sAttr = GetAttribute(sName);
			std::stringstream s(sAttr);
			s >> v;
			return v;
		};
		
		/// Get node name
		String GetName();
		/// Iterate to next node in document (depth first)
		bool NextNode();
		/// Iterate to next sibling
		bool NextSibling();

		/// Perform depth-first search to find the specified node (from current doc position)
		bool GetNode(const String& sName);

		inline void Reset() {
			mpNode = mpRoot;
		};
		inline XmlIterator GetIterator() const {
			return XmlIterator(mpNode);
		};
	};

	class XmlFile : public WtfEngine::GcObject, public XmlIterator
	{
	private:
		XercesDOMParser *	mpParser;
		
	public:
		XmlFile();
		~XmlFile(){
			Unload();
		};
		
		void Load(const String& sFile);
		
		void Unload()
		{
			if(mpParser)
				delete mpParser;
		};

		GC_OBJECT(XmlFile, sizeof(XmlFile) + (mpParser ? sizeof(XercesDOMParser) : 0) + (mpNode ? sizeof(DOMNode) : 0));
	};

#elif defined(__XML_LIBXMLPP__)
	
	class XmlFile : public WtfEngine::GcObject
	{
	private:
		xmlpp::TextReader*	mXmlFile;
		
	public:
		XmlFile()
				: WtfEngine::GcObject(), mXmlFile(NULL) {};
		~XmlFile(){
			Unload();
		};
		
		void Load(String sFile)
		{
			Unload();
			mXmlFile = new xmlpp::TextReader(sFile);
		};
		
		void Unload()
		{
			if(mXmlFile)
				delete mXmlFile;
		};
		
		
		/**** Delegates ****/ 
		
		inline String GetXml(){
			return mXmlFile->read_outer_xml();
		};
		inline String GetText(){
			return mXmlFile->read_string();
		};
		inline String GetAttribute(String sName){
			return mXmlFile->get_attribute(sName);
		};
		template <typename T>
		inline T GetAttribute(String sName){
			T v;
			String sAttr = GetAttribute(sName);
			std::stringstream s(sAttr);
			s >> v;
			return v;
		};
		
		inline String GetName(){
			return mXmlFile->get_name();
		};
		
		inline bool NextNode(){
			return mXmlFile->read();
		};
		inline bool NextAttribute(){
			return mXmlFile->read_attribute_value();
		};
		
		typedef WtfEngine::GcReference<XmlFile>	tRef;
	};
#endif
}

#endif
